{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:30:03.633228Z",
     "start_time": "2025-01-23T02:30:01.375464Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:01.835957Z",
     "iopub.status.busy": "2025-01-24T06:13:01.835684Z",
     "iopub.status.idle": "2025-01-24T06:13:06.845967Z",
     "shell.execute_reply": "2025-01-24T06:13:06.845490Z",
     "shell.execute_reply.started": "2025-01-24T06:13:01.835938Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
      "  from .autonotebook import tqdm as notebook_tqdm\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=10, micro=14, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.0\n",
      "numpy 1.26.4\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.0\n",
      "torch 2.5.1+cu124\n",
      "cuda:0\n"
     ]
    }
   ],
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "\n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n",
    "\n",
    "seed = 42\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 准备数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:06.847210Z",
     "iopub.status.busy": "2025-01-24T06:13:06.846741Z",
     "iopub.status.idle": "2025-01-24T06:13:10.718508Z",
     "shell.execute_reply": "2025-01-24T06:13:10.717946Z",
     "shell.execute_reply.started": "2025-01-24T06:13:06.847191Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://mirrors.cloud.aliyuncs.com/pypi/simple\n",
      "Requirement already satisfied: tensorflow in /usr/local/lib/python3.10/site-packages (2.18.0)\n",
      "Requirement already satisfied: absl-py>=1.0.0 in /usr/local/lib/python3.10/site-packages (from tensorflow) (2.1.0)\n",
      "Requirement already satisfied: astunparse>=1.6.0 in /usr/local/lib/python3.10/site-packages (from tensorflow) (1.6.3)\n",
      "Requirement already satisfied: flatbuffers>=24.3.25 in /usr/local/lib/python3.10/site-packages (from tensorflow) (25.1.21)\n",
      "Requirement already satisfied: gast!=0.5.0,!=0.5.1,!=0.5.2,>=0.2.1 in /usr/local/lib/python3.10/site-packages (from tensorflow) (0.6.0)\n",
      "Requirement already satisfied: google-pasta>=0.1.1 in /usr/local/lib/python3.10/site-packages (from tensorflow) (0.2.0)\n",
      "Requirement already satisfied: libclang>=13.0.0 in /usr/local/lib/python3.10/site-packages (from tensorflow) (18.1.1)\n",
      "Requirement already satisfied: opt-einsum>=2.3.2 in /usr/local/lib/python3.10/site-packages (from tensorflow) (3.4.0)\n",
      "Requirement already satisfied: packaging in /usr/local/lib/python3.10/site-packages (from tensorflow) (24.2)\n",
      "Requirement already satisfied: protobuf!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0dev,>=3.20.3 in /usr/local/lib/python3.10/site-packages (from tensorflow) (5.29.2)\n",
      "Requirement already satisfied: requests<3,>=2.21.0 in /usr/local/lib/python3.10/site-packages (from tensorflow) (2.32.3)\n",
      "Requirement already satisfied: setuptools in /usr/local/lib/python3.10/site-packages (from tensorflow) (69.5.1)\n",
      "Requirement already satisfied: six>=1.12.0 in /usr/local/lib/python3.10/site-packages (from tensorflow) (1.17.0)\n",
      "Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.10/site-packages (from tensorflow) (2.5.0)\n",
      "Requirement already satisfied: typing-extensions>=3.6.6 in /usr/local/lib/python3.10/site-packages (from tensorflow) (4.12.2)\n",
      "Requirement already satisfied: wrapt>=1.11.0 in /usr/local/lib/python3.10/site-packages (from tensorflow) (1.17.0)\n",
      "Requirement already satisfied: grpcio<2.0,>=1.24.3 in /usr/local/lib/python3.10/site-packages (from tensorflow) (1.69.0)\n",
      "Requirement already satisfied: tensorboard<2.19,>=2.18 in /usr/local/lib/python3.10/site-packages (from tensorflow) (2.18.0)\n",
      "Requirement already satisfied: keras>=3.5.0 in /usr/local/lib/python3.10/site-packages (from tensorflow) (3.8.0)\n",
      "Requirement already satisfied: numpy<2.1.0,>=1.26.0 in /usr/local/lib/python3.10/site-packages (from tensorflow) (1.26.4)\n",
      "Requirement already satisfied: h5py>=3.11.0 in /usr/local/lib/python3.10/site-packages (from tensorflow) (3.12.1)\n",
      "Requirement already satisfied: ml-dtypes<0.5.0,>=0.4.0 in /usr/local/lib/python3.10/site-packages (from tensorflow) (0.4.1)\n",
      "Requirement already satisfied: tensorflow-io-gcs-filesystem>=0.23.1 in /usr/local/lib/python3.10/site-packages (from tensorflow) (0.37.1)\n",
      "Requirement already satisfied: wheel<1.0,>=0.23.0 in /usr/local/lib/python3.10/site-packages (from astunparse>=1.6.0->tensorflow) (0.44.0)\n",
      "Requirement already satisfied: rich in /usr/local/lib/python3.10/site-packages (from keras>=3.5.0->tensorflow) (13.9.4)\n",
      "Requirement already satisfied: namex in /usr/local/lib/python3.10/site-packages (from keras>=3.5.0->tensorflow) (0.0.8)\n",
      "Requirement already satisfied: optree in /usr/local/lib/python3.10/site-packages (from keras>=3.5.0->tensorflow) (0.14.0)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/site-packages (from requests<3,>=2.21.0->tensorflow) (3.4.1)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/site-packages (from requests<3,>=2.21.0->tensorflow) (3.10)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/site-packages (from requests<3,>=2.21.0->tensorflow) (2.3.0)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/site-packages (from requests<3,>=2.21.0->tensorflow) (2024.12.14)\n",
      "Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.10/site-packages (from tensorboard<2.19,>=2.18->tensorflow) (3.7)\n",
      "Requirement already satisfied: tensorboard-data-server<0.8.0,>=0.7.0 in /usr/local/lib/python3.10/site-packages (from tensorboard<2.19,>=2.18->tensorflow) (0.7.2)\n",
      "Requirement already satisfied: werkzeug>=1.0.1 in /usr/local/lib/python3.10/site-packages (from tensorboard<2.19,>=2.18->tensorflow) (3.1.3)\n",
      "Requirement already satisfied: MarkupSafe>=2.1.1 in /usr/local/lib/python3.10/site-packages (from werkzeug>=1.0.1->tensorboard<2.19,>=2.18->tensorflow) (2.1.5)\n",
      "Requirement already satisfied: markdown-it-py>=2.2.0 in /usr/local/lib/python3.10/site-packages (from rich->keras>=3.5.0->tensorflow) (3.0.0)\n",
      "Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /usr/local/lib/python3.10/site-packages (from rich->keras>=3.5.0->tensorflow) (2.19.0)\n",
      "Requirement already satisfied: mdurl~=0.1 in /usr/local/lib/python3.10/site-packages (from markdown-it-py>=2.2.0->rich->keras>=3.5.0->tensorflow) (0.1.2)\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
      "\u001b[0m\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.3.2\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\u001b[0m\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "!pip install tensorflow"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:39:55.946033Z",
     "start_time": "2025-01-23T02:39:51.151867Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:10.719805Z",
     "iopub.status.busy": "2025-01-24T06:13:10.719256Z",
     "iopub.status.idle": "2025-01-24T06:13:16.385852Z",
     "shell.execute_reply": "2025-01-24T06:13:16.385357Z",
     "shell.execute_reply.started": "2025-01-24T06:13:10.719776Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2025-01-24 14:13:11.166555: I tensorflow/core/util/port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n",
      "2025-01-24 14:13:11.397251: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:477] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered\n",
      "WARNING: All log messages before absl::InitializeLog() is called are written to STDERR\n",
      "E0000 00:00:1737699191.484887     301 cuda_dnn.cc:8310] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered\n",
      "E0000 00:00:1737699191.510387     301 cuda_blas.cc:1418] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n",
      "2025-01-24 14:13:11.726329: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.\n",
      "To enable the following instructions: AVX2 AVX512F AVX512_VNNI FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.\n"
     ]
    }
   ],
   "source": [
    "from tensorflow import keras  #这里的波浪线不用管\n",
    "\n",
    "#用karas有的数据集imdb，电影分类,分电影是积极的，还是消极的\n",
    "imdb = keras.datasets.imdb\n",
    "#载入数据使用下面两个参数\n",
    "vocab_size = 10000  #词典大小，仅保留训练数据中前10000个最经常出现的单词，低频单词被舍弃\n",
    "index_from = 3  #0,1,2,3空出来做别的事\n",
    "#前一万个词出现词频最高的会保留下来进行处理，后面的作为特殊字符处理，\n",
    "# 小于3的id都是特殊字符，下面代码有写\n",
    "# 需要注意的一点是取出来的词表还是从1开始的，需要做处理\n",
    "(train_data, train_labels), (test_data, test_labels) = imdb.load_data(\n",
    "    num_words=vocab_size, index_from=index_from)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:40:46.265356Z",
     "start_time": "2025-01-23T02:40:46.262283Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:16.387732Z",
     "iopub.status.busy": "2025-01-24T06:13:16.387287Z",
     "iopub.status.idle": "2025-01-24T06:13:16.391305Z",
     "shell.execute_reply": "2025-01-24T06:13:16.390883Z",
     "shell.execute_reply.started": "2025-01-24T06:13:16.387714Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "numpy.ndarray"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(train_labels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-29T01:31:13.347945400Z",
     "start_time": "2024-07-29T01:31:13.335467900Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:16.391950Z",
     "iopub.status.busy": "2025-01-24T06:13:16.391785Z",
     "iopub.status.idle": "2025-01-24T06:13:16.394515Z",
     "shell.execute_reply": "2025-01-24T06:13:16.394106Z",
     "shell.execute_reply.started": "2025-01-24T06:13:16.391934Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'numpy.ndarray'>\n"
     ]
    }
   ],
   "source": [
    "print(type(train_data))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:41:12.808625Z",
     "start_time": "2025-01-23T02:41:12.805249Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:16.395300Z",
     "iopub.status.busy": "2025-01-24T06:13:16.394971Z",
     "iopub.status.idle": "2025-01-24T06:13:16.398091Z",
     "shell.execute_reply": "2025-01-24T06:13:16.397689Z",
     "shell.execute_reply.started": "2025-01-24T06:13:16.395284Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(25000,)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_data.shape  #每个样本是一段话，每个单词用一个数字表示"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:41:20.297524Z",
     "start_time": "2025-01-23T02:41:20.294848Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:16.398915Z",
     "iopub.status.busy": "2025-01-24T06:13:16.398563Z",
     "iopub.status.idle": "2025-01-24T06:13:16.401641Z",
     "shell.execute_reply": "2025-01-24T06:13:16.401242Z",
     "shell.execute_reply.started": "2025-01-24T06:13:16.398898Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "list"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(train_data[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:46:53.671155Z",
     "start_time": "2025-01-23T02:46:53.667106Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:16.402415Z",
     "iopub.status.busy": "2025-01-24T06:13:16.402089Z",
     "iopub.status.idle": "2025-01-24T06:13:16.406179Z",
     "shell.execute_reply": "2025-01-24T06:13:16.405787Z",
     "shell.execute_reply.started": "2025-01-24T06:13:16.402398Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1,\n",
       " 14,\n",
       " 47,\n",
       " 8,\n",
       " 30,\n",
       " 31,\n",
       " 7,\n",
       " 4,\n",
       " 249,\n",
       " 108,\n",
       " 7,\n",
       " 4,\n",
       " 5974,\n",
       " 54,\n",
       " 61,\n",
       " 369,\n",
       " 13,\n",
       " 71,\n",
       " 149,\n",
       " 14,\n",
       " 22,\n",
       " 112,\n",
       " 4,\n",
       " 2401,\n",
       " 311,\n",
       " 12,\n",
       " 16,\n",
       " 3711,\n",
       " 33,\n",
       " 75,\n",
       " 43,\n",
       " 1829,\n",
       " 296,\n",
       " 4,\n",
       " 86,\n",
       " 320,\n",
       " 35,\n",
       " 534,\n",
       " 19,\n",
       " 263,\n",
       " 4821,\n",
       " 1301,\n",
       " 4,\n",
       " 1873,\n",
       " 33,\n",
       " 89,\n",
       " 78,\n",
       " 12,\n",
       " 66,\n",
       " 16,\n",
       " 4,\n",
       " 360,\n",
       " 7,\n",
       " 4,\n",
       " 58,\n",
       " 316,\n",
       " 334,\n",
       " 11,\n",
       " 4,\n",
       " 1716,\n",
       " 43,\n",
       " 645,\n",
       " 662,\n",
       " 8,\n",
       " 257,\n",
       " 85,\n",
       " 1200,\n",
       " 42,\n",
       " 1228,\n",
       " 2578,\n",
       " 83,\n",
       " 68,\n",
       " 3912,\n",
       " 15,\n",
       " 36,\n",
       " 165,\n",
       " 1539,\n",
       " 278,\n",
       " 36,\n",
       " 69,\n",
       " 2,\n",
       " 780,\n",
       " 8,\n",
       " 106,\n",
       " 14,\n",
       " 6905,\n",
       " 1338,\n",
       " 18,\n",
       " 6,\n",
       " 22,\n",
       " 12,\n",
       " 215,\n",
       " 28,\n",
       " 610,\n",
       " 40,\n",
       " 6,\n",
       " 87,\n",
       " 326,\n",
       " 23,\n",
       " 2300,\n",
       " 21,\n",
       " 23,\n",
       " 22,\n",
       " 12,\n",
       " 272,\n",
       " 40,\n",
       " 57,\n",
       " 31,\n",
       " 11,\n",
       " 4,\n",
       " 22,\n",
       " 47,\n",
       " 6,\n",
       " 2307,\n",
       " 51,\n",
       " 9,\n",
       " 170,\n",
       " 23,\n",
       " 595,\n",
       " 116,\n",
       " 595,\n",
       " 1352,\n",
       " 13,\n",
       " 191,\n",
       " 79,\n",
       " 638,\n",
       " 89,\n",
       " 2,\n",
       " 14,\n",
       " 9,\n",
       " 8,\n",
       " 106,\n",
       " 607,\n",
       " 624,\n",
       " 35,\n",
       " 534,\n",
       " 6,\n",
       " 227,\n",
       " 7,\n",
       " 129,\n",
       " 113]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_data[2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:49:44.840885Z",
     "start_time": "2025-01-23T02:49:44.838238Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:16.406871Z",
     "iopub.status.busy": "2025-01-24T06:13:16.406714Z",
     "iopub.status.idle": "2025-01-24T06:13:16.409632Z",
     "shell.execute_reply": "2025-01-24T06:13:16.409239Z",
     "shell.execute_reply.started": "2025-01-24T06:13:16.406857Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "218"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(train_data[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:49:51.448330Z",
     "start_time": "2025-01-23T02:49:51.445153Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:16.411414Z",
     "iopub.status.busy": "2025-01-24T06:13:16.411143Z",
     "iopub.status.idle": "2025-01-24T06:13:16.414939Z",
     "shell.execute_reply": "2025-01-24T06:13:16.414577Z",
     "shell.execute_reply.started": "2025-01-24T06:13:16.411398Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "189"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(train_data[1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:41:31.762074Z",
     "start_time": "2025-01-23T02:41:31.759252Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:16.415617Z",
     "iopub.status.busy": "2025-01-24T06:13:16.415351Z",
     "iopub.status.idle": "2025-01-24T06:13:16.418454Z",
     "shell.execute_reply": "2025-01-24T06:13:16.418094Z",
     "shell.execute_reply.started": "2025-01-24T06:13:16.415603Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 0, 0, 1, 0, 0, 1, 0, 1, 0])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_labels[0:10]  #二分类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-29T01:31:13.411229100Z",
     "start_time": "2024-07-29T01:31:13.376232500Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:16.419131Z",
     "iopub.status.busy": "2025-01-24T06:13:16.418887Z",
     "iopub.status.idle": "2025-01-24T06:13:16.421638Z",
     "shell.execute_reply": "2025-01-24T06:13:16.421213Z",
     "shell.execute_reply.started": "2025-01-24T06:13:16.419116Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "train 25000 (25000,)\n",
      "test 25000 (25000,)\n"
     ]
    }
   ],
   "source": [
    "print(\"train\", len(train_data), train_labels.shape)  #25000个样本，每个样本是一段话，每个单词用一个数字表示\n",
    "print(\"test\", len(test_data), test_labels.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:42:10.377522Z",
     "start_time": "2025-01-23T02:42:09.842094Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:16.422208Z",
     "iopub.status.busy": "2025-01-24T06:13:16.422074Z",
     "iopub.status.idle": "2025-01-24T06:13:16.464329Z",
     "shell.execute_reply": "2025-01-24T06:13:16.463892Z",
     "shell.execute_reply.started": "2025-01-24T06:13:16.422194Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "88584\n",
      "<class 'dict'>\n"
     ]
    }
   ],
   "source": [
    "#载入词表，看下词表长度，词表就像英语字典\n",
    "word_index = imdb.get_word_index()\n",
    "print(len(word_index))\n",
    "print(type(word_index))\n",
    "#词表虽然有8万多，但是我们只载入了最高频的1万词！！！！"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 构造 word2idx 和 idx2word"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:44:32.024144Z",
     "start_time": "2025-01-23T02:44:32.008569Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:16.465058Z",
     "iopub.status.busy": "2025-01-24T06:13:16.464854Z",
     "iopub.status.idle": "2025-01-24T06:13:16.492239Z",
     "shell.execute_reply": "2025-01-24T06:13:16.491698Z",
     "shell.execute_reply.started": "2025-01-24T06:13:16.465041Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "word2idx = {word: idx + 3 for word, idx in word_index.items()}  # 0,1,2,3空出来做别的事,这里的idx是从1开始的,所以加3\n",
    "word2idx.update({\n",
    "    \"[PAD]\": 0,  # 填充 token\n",
    "    \"[BOS]\": 1,  # begin of sentence\n",
    "    \"[UNK]\": 2,  # 未知 token\n",
    "    \"[EOS]\": 3,  # end of sentence\n",
    "})\n",
    "\n",
    "idx2word = {idx: word for word, idx in word2idx.items()}  # 反向词典,id变为单词"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:48:54.831013Z",
     "start_time": "2025-01-23T02:48:54.828534Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:16.493001Z",
     "iopub.status.busy": "2025-01-24T06:13:16.492791Z",
     "iopub.status.idle": "2025-01-24T06:13:16.495591Z",
     "shell.execute_reply": "2025-01-24T06:13:16.495161Z",
     "shell.execute_reply.started": "2025-01-24T06:13:16.492984Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "182\n"
     ]
    }
   ],
   "source": [
    "print(word2idx[\"world\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:44:34.705341Z",
     "start_time": "2025-01-23T02:44:34.702003Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:16.496294Z",
     "iopub.status.busy": "2025-01-24T06:13:16.496048Z",
     "iopub.status.idle": "2025-01-24T06:13:16.499185Z",
     "shell.execute_reply": "2025-01-24T06:13:16.498769Z",
     "shell.execute_reply.started": "2025-01-24T06:13:16.496279Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'the'"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "idx2word[4]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:52:21.918916Z",
     "start_time": "2025-01-23T02:52:21.261439Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:16.500023Z",
     "iopub.status.busy": "2025-01-24T06:13:16.499668Z",
     "iopub.status.idle": "2025-01-24T06:13:17.401148Z",
     "shell.execute_reply": "2025-01-24T06:13:17.400683Z",
     "shell.execute_reply.started": "2025-01-24T06:13:16.500005Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAigAAAGdCAYAAAA44ojeAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAO+RJREFUeJzt3Xl4FFW+//FPb4mJZjGBbGPYlUUCAmqIC8IlCnFFcAYUHVAGRAMjoIjxqqDee8Oo4zKKOI4Kziji6GVxcMSHHZeAgCAgiIAoqAkwMiQskvRyfn94qZ8t6UCgU90N79fz1OPpqtPV3zq0qW+fU3XKYYwxAgAAiCLOSAcAAADwSyQoAAAg6pCgAACAqEOCAgAAog4JCgAAiDokKAAAIOqQoAAAgKhDggIAAKKOO9IBHI9AIKDvv/9eSUlJcjgckQ4HAAAcA2OM9u3bp5ycHDmddfeRxGSC8v333ys3NzfSYQAAgOOwY8cOnXXWWXXWickEJSkpSdJPB5icnBzhaAAAwLGoqqpSbm6udR6vS0wmKIeHdZKTk0lQYojf79eyZcskSV27dpXL5YpwRACASDiWyzNiMkFBbPL7/Zo/f74k6YILLiBBAQCERIIC2zidTnXs2NEqAwAQCgkKbON2u9WnT59IhwEAiAH1SlBKS0s1Y8YMffHFF0pISNBFF12kP/zhD2rdurVV59ChQ7r77rs1ffp0VVdXq1evXnr++eeVmZlp1dm+fbvuuOMOLVq0SGeccYYGDRqk0tJSud3kSwBwMjDGyOfzye/3RzoU2MjlcsntdodlCpB6ZQRLlixRcXGxLrjgAvl8Pt1///264oortGHDBp1++umSpNGjR+vdd9/VW2+9pZSUFI0YMUJ9+/bVRx99JOmn6xCuuuoqZWVl6eOPP1Z5ebl++9vfyuPx6H/+539O+IAAAJFVU1Oj8vJyHTx4MNKhIAISExOVnZ2tuLi4E9qPwxhjjvfNu3fvVkZGhpYsWaJu3bqpsrJSjRs31rRp03TDDTdIkr744gu1bdtWZWVl6tq1q9577z1dffXV+v77761elRdeeEHjxo3T7t27j+mAqqqqlJKSosrKSu7iiSE1NTV68sknJUljxow54S8vgOgTCAS0efNmuVwuNW7cWHFxcUyoeYowxqimpka7d++W3+/X2WeffcT1hvU5f5/QmEplZaUkKS0tTZK0atUqeb1eFRYWWnXatGmjJk2aWAlKWVmZ8vLygoZ8evXqpTvuuEOff/65OnXqdMTnVFdXq7q6OugAEZt+/u8I4ORTU1OjQCCg3NxcJSYmRjoc2CwhIUEej0fffPONampqdNpppx33vo47QQkEAho1apQuvvhitW/fXpJUUVGhuLg4paamBtXNzMxURUWFVefnycnh7Ye31aa0tFQPP/zw8YaKKOHxeDRixAirDODkxZ16p65w/dsf916Ki4u1fv16TZ8+PSyB1KWkpESVlZXWsmPHjgb/TISfw+FQenq60tPT6fIFANTpuBKUESNGaM6cOVq0aFHQXPpZWVmqqanR3r17g+rv3LlTWVlZVp2dO3cesf3wttrEx8dbs8YyeywA4GTncDg0a9asSIchSZowYYLOO+882z+3XgmKMUYjRozQzJkztXDhQjVv3jxoe5cuXeTxeLRgwQJr3aZNm7R9+3YVFBRIkgoKCrRu3Trt2rXLqjNv3jwlJyerXbt2J3IsiHJ+v1+ffPKJPvnkE249BIAoFE2JUb2uQSkuLta0adM0e/ZsJSUlWdeMpKSkKCEhQSkpKRoyZIjGjBmjtLQ0JScna+TIkSooKFDXrl0lSVdccYXatWunW265RY899pgqKir0wAMPqLi4WPHx8eE/QkQNv9+v9957T5J03nnnMdU9ACCkevWgTJ48WZWVlerevbuys7Ot5c0337TqPPXUU7r66qvVr18/devWTVlZWZoxY4a13eVyac6cOXK5XCooKNDNN9+s3/72t3rkkUfCd1SISk6nU+3atVO7du24gA5A1OnevbtGjhypUaNG6cwzz1RmZqb+8pe/6MCBA7r11luVlJSkVq1aWT+0pJ9+eA0ZMkTNmzdXQkKCWrdurWeeecbafujQIZ177rkaNmyYtW7r1q1KSkrSK6+8csyx7dixQ7/5zW+UmpqqtLQ0XXfddfr666+t7YMHD1afPn30xBNPKDs7W+np6SouLpbX67XqlJeX66qrrlJCQoKaN2+uadOmqVmzZnr66aclSc2aNZMkXX/99XI4HNbrw/72t7+pWbNmSklJ0YABA7Rv375jjv+4mBhUWVlpJJnKyspIhwIA+Jkff/zRbNiwwfz4449HbKuurjbV1dUmEAhY63w+n6murjZerzesdY/HZZddZpKSksyjjz5qvvzyS/Poo48a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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 选择 max_length\n",
    "length_collect = {}\n",
    "#统计样本中每个长度出现的次数\n",
    "for text in train_data:\n",
    "    length = len(text)  #句子长度\n",
    "    length_collect[length] = length_collect.get(length, 0) + 1  #统计长度的频率\n",
    "\n",
    "MAX_LENGTH = 500\n",
    "plt.bar(length_collect.keys(), length_collect.values())  #长度分布图\n",
    "plt.axvline(MAX_LENGTH, label=\"max length\", c=\"gray\", ls=\":\")  #画一条线，可以看到大部分都在500以内\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:51:50.164827Z",
     "start_time": "2025-01-23T02:51:50.076652Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:17.402036Z",
     "iopub.status.busy": "2025-01-24T06:13:17.401729Z",
     "iopub.status.idle": "2025-01-24T06:13:17.574898Z",
     "shell.execute_reply": "2025-01-24T06:13:17.574405Z",
     "shell.execute_reply.started": "2025-01-24T06:13:17.402017Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#想对句子长度画个直方图，看看长度分布\n",
    "length_list = [len(text) for text in train_data]\n",
    "plt.hist(length_list, bins=50)\n",
    "plt.xlabel(\"length\")\n",
    "plt.ylabel(\"frequency\")\n",
    "plt.axvline(500, label=\"max length\", c=\"gray\", ls=\":\")\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-29T01:31:15.171825200Z",
     "start_time": "2024-07-29T01:31:15.162820900Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:17.575633Z",
     "iopub.status.busy": "2025-01-24T06:13:17.575460Z",
     "iopub.status.idle": "2025-01-24T06:13:17.579264Z",
     "shell.execute_reply": "2025-01-24T06:13:17.578809Z",
     "shell.execute_reply.started": "2025-01-24T06:13:17.575616Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[218, 189, 141, 550, 147, 43, 123, 562, 233, 130]"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "length_list[0:10]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T02:57:15.067528Z",
     "start_time": "2025-01-23T02:57:15.064103Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:17.580240Z",
     "iopub.status.busy": "2025-01-24T06:13:17.579868Z",
     "iopub.status.idle": "2025-01-24T06:13:17.583867Z",
     "shell.execute_reply": "2025-01-24T06:13:17.583509Z",
     "shell.execute_reply.started": "2025-01-24T06:13:17.580217Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[['hello', 'world'],\n",
       " ['tokenize', 'text', 'datas', 'with', 'batch'],\n",
       " ['this', 'is', 'a', 'test']]"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "raw_text = [\"hello world\".split(), \"tokenize text datas with batch\".split(), \"this is a test\".split()]\n",
    "raw_text"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Tokenizer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T03:08:56.832821Z",
     "start_time": "2025-01-23T03:08:56.827315Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:17.584600Z",
     "iopub.status.busy": "2025-01-24T06:13:17.584291Z",
     "iopub.status.idle": "2025-01-24T06:13:17.617158Z",
     "shell.execute_reply": "2025-01-24T06:13:17.616725Z",
     "shell.execute_reply.started": "2025-01-24T06:13:17.584585Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "raw text\n",
      "['hello', 'world']\n",
      "['tokenize', 'text', 'datas', 'with', 'batch']\n",
      "['this', 'is', 'a', 'test']\n",
      "indices\n",
      "tensor([   1, 4825,  182,    3,    0,    0,    0])\n",
      "tensor([    1,     2,  3004,     2,    19, 19233,     3])\n",
      "tensor([   1,   14,    9,    6, 2181,    3,    0])\n"
     ]
    }
   ],
   "source": [
    "class Tokenizer:\n",
    "    def __init__(self, word2idx, idx2word, max_length=500, pad_idx=0, bos_idx=1, eos_idx=3, unk_idx=2):\n",
    "        self.word2idx = word2idx  #词表,单词到id\n",
    "        self.idx2word = idx2word  #词表，id到单词\n",
    "        self.max_length = max_length\n",
    "        self.pad_idx = pad_idx  #填充\n",
    "        self.bos_idx = bos_idx  #开始\n",
    "        self.eos_idx = eos_idx  #结束\n",
    "        self.unk_idx = unk_idx  #未知，未出现在最高频词表中的词\n",
    "\n",
    "    def encode(self, text_list):\n",
    "        \"\"\"\n",
    "        将文本列表转化为索引列表\n",
    "        :param text_list:当前批次的文本列表\n",
    "        :return:\n",
    "        \"\"\"\n",
    "        max_length = min(self.max_length, 2 + max(\n",
    "            [len(text) for text in text_list]))  #最大长度，最大长度是500，但是如果句子长度小于500，就取句子长度（句子长度是本组句子中最长的），2是为了留出开始和结束的位置\n",
    "        indices = []\n",
    "        for text in text_list:\n",
    "            index = [self.word2idx.get(word, self.unk_idx) for word in text]  #单词转化为id，未知的词用unk_idx代替\n",
    "            index = [self.bos_idx] + index + [self.eos_idx]  #添加开始和结束\n",
    "            if len(index) < max_length:\n",
    "                index = index + [self.pad_idx] * (max_length - len(index))  #填充0\n",
    "            else:\n",
    "                index = index[:max_length]  #如果句子长度大于500，就截断\n",
    "            indices.append(index)\n",
    "        return torch.tensor(indices)  #二维列表转化为tensor\n",
    "\n",
    "    def decode(self, indices_list, remove_bos=True, remove_eos=True, remove_pad=True, split=False):\n",
    "        \"\"\"\n",
    "        将索引列表转化为文本列表\n",
    "        :param indices_list:某批次的索引列表\n",
    "        :param remove_bos:\n",
    "        :param remove_eos:\n",
    "        :param remove_pad:\n",
    "        :param split:\n",
    "        :return:\n",
    "        \"\"\"\n",
    "        text_list = []\n",
    "        for indices in indices_list:\n",
    "            text = []\n",
    "            for index in indices:\n",
    "                word = self.idx2word.get(index, \"[UNK]\")\n",
    "                if remove_bos and word == \"[BOS]\":\n",
    "                    continue\n",
    "                if remove_eos and word == \"[EOS]\":\n",
    "                    break\n",
    "                if remove_pad and word == \"[PAD]\":\n",
    "                    break\n",
    "                text.append(word)\n",
    "            text_list.append(\" \".join(text) if not split else text)\n",
    "        return text_list\n",
    "\n",
    "\n",
    "tokenizer = Tokenizer(word2idx=word2idx, idx2word=idx2word)\n",
    "raw_text = [\"hello world\".split(), \"tokenize text datas with batch\".split(), \"this is a test\".split()]\n",
    "indices = tokenizer.encode(raw_text)  #encode支持批量处理\n",
    "print(\"raw text\")\n",
    "for raw in raw_text:\n",
    "    print(raw)\n",
    "print(\"indices\")\n",
    "for index in indices:\n",
    "    print(index)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T03:09:52.109310Z",
     "start_time": "2025-01-23T03:09:52.106674Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:17.617826Z",
     "iopub.status.busy": "2025-01-24T06:13:17.617659Z",
     "iopub.status.idle": "2025-01-24T06:13:17.620835Z",
     "shell.execute_reply": "2025-01-24T06:13:17.620392Z",
     "shell.execute_reply.started": "2025-01-24T06:13:17.617811Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "decode text----------\n",
      "[BOS] hello world [EOS] [PAD] [PAD] [PAD]\n",
      "[BOS] [UNK] text [UNK] with batch [EOS]\n",
      "[BOS] this is a test [EOS] [PAD]\n"
     ]
    }
   ],
   "source": [
    "decode_text = tokenizer.decode(indices.tolist(), remove_bos=False, remove_eos=False, remove_pad=False)\n",
    "print(\"decode text----------\")\n",
    "for decode in decode_text:\n",
    "    print(decode)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T03:10:17.403043Z",
     "start_time": "2025-01-23T03:10:17.399832Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:17.621447Z",
     "iopub.status.busy": "2025-01-24T06:13:17.621260Z",
     "iopub.status.idle": "2025-01-24T06:13:17.624344Z",
     "shell.execute_reply": "2025-01-24T06:13:17.624007Z",
     "shell.execute_reply.started": "2025-01-24T06:13:17.621432Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([list([1, 14, 22, 16, 43, 530, 973, 1622, 1385, 65, 458, 4468, 66, 3941, 4, 173, 36, 256, 5, 25, 100, 43, 838, 112, 50, 670, 2, 9, 35, 480, 284, 5, 150, 4, 172, 112, 167, 2, 336, 385, 39, 4, 172, 4536, 1111, 17, 546, 38, 13, 447, 4, 192, 50, 16, 6, 147, 2025, 19, 14, 22, 4, 1920, 4613, 469, 4, 22, 71, 87, 12, 16, 43, 530, 38, 76, 15, 13, 1247, 4, 22, 17, 515, 17, 12, 16, 626, 18, 2, 5, 62, 386, 12, 8, 316, 8, 106, 5, 4, 2223, 5244, 16, 480, 66, 3785, 33, 4, 130, 12, 16, 38, 619, 5, 25, 124, 51, 36, 135, 48, 25, 1415, 33, 6, 22, 12, 215, 28, 77, 52, 5, 14, 407, 16, 82, 2, 8, 4, 107, 117, 5952, 15, 256, 4, 2, 7, 3766, 5, 723, 36, 71, 43, 530, 476, 26, 400, 317, 46, 7, 4, 2, 1029, 13, 104, 88, 4, 381, 15, 297, 98, 32, 2071, 56, 26, 141, 6, 194, 7486, 18, 4, 226, 22, 21, 134, 476, 26, 480, 5, 144, 30, 5535, 18, 51, 36, 28, 224, 92, 25, 104, 4, 226, 65, 16, 38, 1334, 88, 12, 16, 283, 5, 16, 4472, 113, 103, 32, 15, 16, 5345, 19, 178, 32])],\n",
       "      dtype=object)"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_data[0:1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T03:11:00.596938Z",
     "start_time": "2025-01-23T03:11:00.593995Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:17.624955Z",
     "iopub.status.busy": "2025-01-24T06:13:17.624774Z",
     "iopub.status.idle": "2025-01-24T06:13:17.627901Z",
     "shell.execute_reply": "2025-01-24T06:13:17.627546Z",
     "shell.execute_reply.started": "2025-01-24T06:13:17.624940Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[\"[BOS] this film was just brilliant casting location scenery story direction everyone's really suited the part they played and you could just imagine being there robert [UNK] is an amazing actor and now the same being director [UNK] father came from the same scottish island as myself so i loved the fact there was a real connection with this film the witty remarks throughout the film were great it was just brilliant so much that i bought the film as soon as it was released for [UNK] and would recommend it to everyone to watch and the fly fishing was amazing really cried at the end it was so sad and you know what they say if you cry at a film it must have been good and this definitely was also [UNK] to the two little boy's that played the [UNK] of norman and paul they were just brilliant children are often left out of the [UNK] list i think because the stars that play them all grown up are such a big profile for the whole film but these children are amazing and should be praised for what they have done don't you think the whole story was so lovely because it was true and was someone's life after all that was shared with us all\"]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 看看训练集的数据\n",
    "tokenizer.decode(train_data[0:1], remove_bos=False, remove_eos=False, remove_pad=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据集与 DataLoader"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T03:17:52.765531Z",
     "start_time": "2025-01-23T03:17:51.939658Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:17.628435Z",
     "iopub.status.busy": "2025-01-24T06:13:17.628296Z",
     "iopub.status.idle": "2025-01-24T06:13:19.232753Z",
     "shell.execute_reply": "2025-01-24T06:13:19.232267Z",
     "shell.execute_reply.started": "2025-01-24T06:13:17.628421Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "from torch.utils.data import Dataset, DataLoader\n",
    "\n",
    "\n",
    "class IMDBDataset(Dataset):\n",
    "    def __init__(self, data, labels, remain_length=True):\n",
    "        if remain_length:  #字符串输出样本中，是否含有【BOS】和【EOS】，【PAD】\n",
    "            self.data = tokenizer.decode(data, remove_bos=False, remove_eos=False, remove_pad=False)\n",
    "        else:\n",
    "            # 缩减一下数据\n",
    "            self.data = tokenizer.decode(data)\n",
    "        self.labels = labels\n",
    "\n",
    "    def __getitem__(self, index):\n",
    "        text = self.data[index]\n",
    "        label = self.labels[index]\n",
    "        return text, label\n",
    "\n",
    "    def __len__(self):\n",
    "        return len(self.data)\n",
    "\n",
    "\n",
    "def collate_fct(batch):\n",
    "    \"\"\"\n",
    "    将batch数据处理成tensor形式\n",
    "    :param batch:\n",
    "    :return:\n",
    "    \"\"\"\n",
    "    text_list = [item[0].split() for item in batch]  #batch是128样本，每个样本类型是元组，第一个元素是文本，第二个元素是标签\n",
    "    label_list = [item[1] for item in batch]\n",
    "    text_list = tokenizer.encode(text_list).to(dtype=torch.int)  # 文本转化为索引\n",
    "    return text_list, torch.tensor(label_list).reshape(-1, 1).to(dtype=torch.float)\n",
    "\n",
    "\n",
    "train_ds = IMDBDataset(train_data, train_labels)\n",
    "test_ds = IMDBDataset(test_data, test_labels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T03:20:13.955987Z",
     "start_time": "2025-01-23T03:20:13.952482Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:19.233491Z",
     "iopub.status.busy": "2025-01-24T06:13:19.233272Z",
     "iopub.status.idle": "2025-01-24T06:13:19.236464Z",
     "shell.execute_reply": "2025-01-24T06:13:19.235994Z",
     "shell.execute_reply.started": "2025-01-24T06:13:19.233475Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "batch_size = 128\n",
    "train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True, collate_fn=collate_fct)  #collate_fn是处理batch的函数\n",
    "test_dl = DataLoader(test_ds, batch_size=batch_size, shuffle=False, collate_fn=collate_fct)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T03:20:16.752101Z",
     "start_time": "2025-01-23T03:20:16.327628Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-24T06:13:41.991127Z",
     "iopub.status.busy": "2025-01-24T06:13:41.990819Z",
     "iopub.status.idle": "2025-01-24T06:13:42.716348Z",
     "shell.execute_reply": "2025-01-24T06:13:42.715814Z",
     "shell.execute_reply.started": "2025-01-24T06:13:41.991108Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n",
      "torch.Size([128, 500]) torch.Size([128, 1])\n"
     ]
    }
   ],
   "source": [
    "#要看到每个batch的长度不同，需要修改batch_size为12\n",
    "i=0\n",
    "for text, label in train_dl:\n",
    "    print(text.shape, label.shape)\n",
    "    i+=1\n",
    "    if i==50:\n",
    "        break"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 定义模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T06:12:27.281115Z",
     "start_time": "2025-01-23T06:12:27.277226Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-01-24T06:19:16.440998Z",
     "iopub.status.busy": "2025-01-24T06:19:16.440660Z",
     "iopub.status.idle": "2025-01-24T06:19:16.455928Z",
     "shell.execute_reply": "2025-01-24T06:19:16.455484Z",
     "shell.execute_reply.started": "2025-01-24T06:19:16.440976Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([1, 3, 1])"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# target output size of 5\n",
    "m = nn.AdaptiveAvgPool1d(1)  # 自适应平均池化\n",
    "input = torch.randn(1, 3, 9)\n",
    "output = m(input)\n",
    "output.size()  #可以看到最后一维变成了1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T06:15:58.688047Z",
     "start_time": "2025-01-23T06:15:58.668766Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:19:24.667397Z",
     "iopub.status.busy": "2025-01-24T06:19:24.667077Z",
     "iopub.status.idle": "2025-01-24T06:19:24.674774Z",
     "shell.execute_reply": "2025-01-24T06:19:24.674320Z",
     "shell.execute_reply.started": "2025-01-24T06:19:24.667363Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "            embeding.weight             paramerters num: 160000\n",
      "              layer.weight              paramerters num: 1024\n",
      "               layer.bias               paramerters num: 64\n",
      "               fc.weight                paramerters num: 64\n",
      "                fc.bias                 paramerters num: 1\n"
     ]
    }
   ],
   "source": [
    "class AddingModel(nn.Module):\n",
    "    def __init__(self, embedding_dim=16, hidden_dim=64, vocab_size=vocab_size):\n",
    "        super(AddingModel, self).__init__()\n",
    "        self.embeding = nn.Embedding(vocab_size, embedding_dim)  # 词嵌入\n",
    "        self.pool = nn.AdaptiveAvgPool1d(1)  # 自适应平均池化,对应tf是全局平均值池化\n",
    "        self.layer = nn.Linear(embedding_dim, hidden_dim)  # 全连接层\n",
    "        self.fc = nn.Linear(hidden_dim, 1)  # 全连接层\n",
    "\n",
    "    def forward(self, x):\n",
    "        # [bs, seq length] [128, 500]  [128,500,10000]--->[128,500,16]\n",
    "        x = self.embeding(x)\n",
    "        # [bs, seq length, embedding_dim]-->[bs, embedding_dim, seq length]，尺寸[128,500,16]--》[128,16,500]\n",
    "        x = x.permute(0, 2, 1)\n",
    "        x = self.pool(x)  # 每个样本变为一个密集向量，在seq_length维度上进行平均池化，[128,16,500]-->[128,16,1]\n",
    "        x=x.squeeze(2)  # [bs, embedding_dim, 1] ->[bs, embedding_dim]\n",
    "        # [bs, embedding_dim] -> [bs, hidden_dim]\n",
    "        x = self.layer(x)\n",
    "        x = self.fc(x)  # [bs, hidden_dim] -> [bs, 1]\n",
    "\n",
    "        return x\n",
    "\n",
    "\n",
    "for key, value in AddingModel().named_parameters():\n",
    "    print(f\"{key:^40}paramerters num: {np.prod(value.shape)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-30T08:35:46.539885600Z",
     "start_time": "2024-04-30T08:35:46.501910500Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1024"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "16 * 64"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T06:21:45.419239Z",
     "start_time": "2025-01-23T06:21:44.942653Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:31:31.166548Z",
     "iopub.status.busy": "2025-01-24T06:31:31.166222Z",
     "iopub.status.idle": "2025-01-24T06:31:31.260789Z",
     "shell.execute_reply": "2025-01-24T06:31:31.260297Z",
     "shell.execute_reply.started": "2025-01-24T06:31:31.166528Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "\n",
    "@torch.no_grad()\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = []\n",
    "    pred_list = []\n",
    "    label_list = []\n",
    "    for datas, labels in dataloader:\n",
    "        datas = datas.to(device)\n",
    "        labels = labels.to(device)\n",
    "        # 前向计算\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)  # 验证集损失\n",
    "        loss_list.append(loss.item())\n",
    "        # 二分类\n",
    "        preds = logits > 0\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "\n",
    "    acc = accuracy_score(label_list, pred_list)\n",
    "    return np.mean(loss_list), acc\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### TensorBoard 可视化\n",
    "\n",
    "\n",
    "训练过程中可以使用如下命令启动tensorboard服务。\n",
    "\n",
    "```shell\n",
    "tensorboard \\\n",
    "    --logdir=runs \\     # log 存放路径\n",
    "    --host 0.0.0.0 \\    # ip\n",
    "    --port 8848         # 端口\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T06:21:50.661437Z",
     "start_time": "2025-01-23T06:21:50.200639Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:31:33.132808Z",
     "iopub.status.busy": "2025-01-24T06:31:33.132293Z",
     "iopub.status.idle": "2025-01-24T06:31:33.272867Z",
     "shell.execute_reply": "2025-01-24T06:31:33.272400Z",
     "shell.execute_reply.started": "2025-01-24T06:31:33.132783Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "\n",
    "class TensorBoardCallback:\n",
    "    def __init__(self, log_dir, flush_secs=10):\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            log_dir (str): dir to write log.\n",
    "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
    "        \"\"\"\n",
    "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
    "\n",
    "    def draw_model(self, model, input_shape):\n",
    "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
    "\n",
    "    def add_loss_scalars(self, step, loss, val_loss):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/loss\",\n",
    "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
    "            global_step=step,\n",
    "        )\n",
    "\n",
    "    def add_acc_scalars(self, step, acc, val_acc):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/accuracy\",\n",
    "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
    "            global_step=step,\n",
    "        )\n",
    "\n",
    "    def add_lr_scalars(self, step, learning_rate):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/learning_rate\",\n",
    "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
    "            global_step=step,\n",
    "\n",
    "        )\n",
    "\n",
    "    def __call__(self, step, **kwargs):\n",
    "        # add loss\n",
    "        loss = kwargs.pop(\"loss\", None)\n",
    "        val_loss = kwargs.pop(\"val_loss\", None)\n",
    "        if loss is not None and val_loss is not None:\n",
    "            self.add_loss_scalars(step, loss, val_loss)\n",
    "        # add acc\n",
    "        acc = kwargs.pop(\"acc\", None)\n",
    "        val_acc = kwargs.pop(\"val_acc\", None)\n",
    "        if acc is not None and val_acc is not None:\n",
    "            self.add_acc_scalars(step, acc, val_acc)\n",
    "        # add lr\n",
    "        learning_rate = kwargs.pop(\"lr\", None)\n",
    "        if learning_rate is not None:\n",
    "            self.add_lr_scalars(step, learning_rate)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save Best\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T06:21:53.510335Z",
     "start_time": "2025-01-23T06:21:53.507562Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:31:36.054505Z",
     "iopub.status.busy": "2025-01-24T06:31:36.054175Z",
     "iopub.status.idle": "2025-01-24T06:31:36.059044Z",
     "shell.execute_reply": "2025-01-24T06:31:36.058600Z",
     "shell.execute_reply.started": "2025-01-24T06:31:36.054483Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
    "        \"\"\"\n",
    "        Save checkpoints each save_epoch epoch. \n",
    "        We save checkpoint by epoch in this implementation.\n",
    "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
    "\n",
    "        Args:\n",
    "            save_dir (str): dir to save checkpoint\n",
    "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
    "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
    "        \"\"\"\n",
    "        self.save_dir = save_dir\n",
    "        self.save_step = save_step\n",
    "        self.save_best_only = save_best_only\n",
    "        self.best_metrics = -1\n",
    "\n",
    "        # mkdir\n",
    "        if not os.path.exists(self.save_dir):\n",
    "            os.mkdir(self.save_dir)\n",
    "\n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return\n",
    "\n",
    "        if self.save_best_only:\n",
    "            assert metric is not None\n",
    "            if metric >= self.best_metrics:\n",
    "                # save checkpoints\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
    "                # update best metrics\n",
    "                self.best_metrics = metric\n",
    "        else:\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Early Stop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T06:21:59.981781Z",
     "start_time": "2025-01-23T06:21:59.979067Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:31:38.241499Z",
     "iopub.status.busy": "2025-01-24T06:31:38.241146Z",
     "iopub.status.idle": "2025-01-24T06:31:38.245374Z",
     "shell.execute_reply": "2025-01-24T06:31:38.244897Z",
     "shell.execute_reply.started": "2025-01-24T06:31:38.241478Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        \"\"\"\n",
    "\n",
    "        Args:\n",
    "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
    "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute \n",
    "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
    "        \"\"\"\n",
    "        self.patience = patience\n",
    "        self.min_delta = min_delta\n",
    "        self.best_metric = -1\n",
    "        self.counter = 0\n",
    "\n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:\n",
    "            # update best metric\n",
    "            self.best_metric = metric\n",
    "            # reset counter \n",
    "            self.counter = 0\n",
    "        else:\n",
    "            self.counter += 1\n",
    "\n",
    "    @property\n",
    "    def early_stop(self):\n",
    "        return self.counter >= self.patience\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T06:24:14.728410Z",
     "start_time": "2025-01-23T06:22:43.117766Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-24T06:31:40.905759Z",
     "iopub.status.busy": "2025-01-24T06:31:40.905287Z",
     "iopub.status.idle": "2025-01-24T06:33:25.695372Z",
     "shell.execute_reply": "2025-01-24T06:33:25.694696Z",
     "shell.execute_reply.started": "2025-01-24T06:31:40.905739Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 80%|████████  | 3136/3920 [01:42<00:25, 30.51it/s, epoch=15]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Early stop at epoch 16 / global_step 3136\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "# 训练\n",
    "def training(\n",
    "        model,\n",
    "        train_loader,\n",
    "        val_loader,\n",
    "        epoch,\n",
    "        loss_fct,\n",
    "        optimizer,\n",
    "        tensorboard_callback=None,\n",
    "        save_ckpt_callback=None,\n",
    "        early_stop_callback=None,\n",
    "        eval_step=500,\n",
    "):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "\n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            # training\n",
    "            for datas, labels in train_loader:\n",
    "                datas = datas.to(device)\n",
    "                labels = labels.to(device)\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等\n",
    "                optimizer.step()\n",
    "                preds = logits > 0 #当sigmoid输出大于0.5时，预测为1，否则预测为0，这里大于0，刚好sigmoid的值是0.5，预测为1\n",
    "\n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())\n",
    "                loss = loss.cpu().item()\n",
    "                # record\n",
    "\n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                })\n",
    "\n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train()\n",
    "\n",
    "                    # 1. 使用 tensorboard 可视化\n",
    "                    if tensorboard_callback is not None:\n",
    "                        tensorboard_callback(\n",
    "                            global_step,\n",
    "                            loss=loss, val_loss=val_loss,\n",
    "                            acc=acc, val_acc=val_acc,\n",
    "                            lr=optimizer.param_groups[0][\"lr\"],\n",
    "                        )\n",
    "\n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
    "\n",
    "                    # 3. 早停 Early Stop\n",
    "                    if early_stop_callback is not None:\n",
    "                        early_stop_callback(val_acc)\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict\n",
    "\n",
    "                # udate step\n",
    "                global_step += 1\n",
    "                pbar.update(1)\n",
    "                pbar.set_postfix({\"epoch\": epoch_id})\n",
    "\n",
    "    return record_dict\n",
    "\n",
    "\n",
    "epoch = 20\n",
    "\n",
    "model = AddingModel()\n",
    "\n",
    "# 1. 定义损失函数 采用二进制交叉熵损失, 先sigmoid再计算交叉熵\n",
    "loss_fct = F.binary_cross_entropy_with_logits\n",
    "# loss_fct =nn.BCEWithLogitsLoss()\n",
    "# 2. 定义优化器 采用 adam\n",
    "# Optimizers specified in the torch.optim package\n",
    "optimizer = torch.optim.Adam(model.parameters(), lr=0.001)\n",
    "\n",
    "# 1. tensorboard 可视化\n",
    "if not os.path.exists(\"runs\"):\n",
    "    os.mkdir(\"runs\")\n",
    "tensorboard_callback = TensorBoardCallback(\"runs/imdb-adding\")\n",
    "# tensorboard_callback.draw_model(model, [1, MAX_LENGTH])\n",
    "# 2. save best\n",
    "if not os.path.exists(\"checkpoints\"):\n",
    "    os.makedirs(\"checkpoints\")\n",
    "save_ckpt_callback = SaveCheckpointsCallback(\"checkpoints/imdb-adding\", save_step=len(train_dl), save_best_only=True)\n",
    "# 3. early stop\n",
    "early_stop_callback = EarlyStopCallback(patience=5)\n",
    "\n",
    "model = model.to(device)\n",
    "record = training(\n",
    "    model,\n",
    "    train_dl,\n",
    "    test_dl,\n",
    "    epoch,\n",
    "    loss_fct,\n",
    "    optimizer,\n",
    "    tensorboard_callback=tensorboard_callback,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=early_stop_callback,\n",
    "    eval_step=len(train_dl)\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T06:25:26.507353Z",
     "start_time": "2025-01-23T06:25:26.400869Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=500):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns)\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):\n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid()\n",
    "        axs[idx].legend()\n",
    "        # axs[idx].set_xticks(range(0, train_df.index[-1], 5000))\n",
    "        # axs[idx].set_xticklabels(map(lambda x: f\"{int(x/1000)}k\", range(0, train_df.index[-1], 5000)))\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "plot_learning_curves(record, sample_step=10)  #横坐标是 steps"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 评估"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-23T06:25:48.506363Z",
     "start_time": "2025-01-23T06:25:46.638163Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss:     0.3052\n",
      "accuracy: 0.8813\n"
     ]
    }
   ],
   "source": [
    "# dataload for evaluating\n",
    "\n",
    "# load checkpoints\n",
    "model.load_state_dict(torch.load(\"checkpoints/imdb-adding/best.ckpt\", weights_only=True,map_location=\"cpu\"))\n",
    "\n",
    "model.eval()\n",
    "loss, acc = evaluating(model, test_dl, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
